//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE.
//
//  This material may not be duplicated in whole or in part, except for 
//  personal use, without the express written consent of the author. 
//
//  Email:  ianier@hotmail.com
//
//  Copyright (C) 1999-2003 Ianier Munoz. All Rights Reserved.

using System;
using System.IO;
using System.Threading;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using XTCast.Wave;
using XTCast.Mp3;
using System.Net;
using CSharpLib;

namespace cswavrec {
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class MainForm : System.Windows.Forms.Form {
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;
		private System.Windows.Forms.Button StopButton;
		private System.Windows.Forms.Button StartButton;
		private System.Windows.Forms.OpenFileDialog OpenDlg;

		public MainForm() {
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing ) {
			if( disposing ) {
				if (components != null) {
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent() {
			this.StartButton = new System.Windows.Forms.Button();
			this.StopButton = new System.Windows.Forms.Button();
			this.OpenDlg = new System.Windows.Forms.OpenFileDialog();
			this.SuspendLayout();
			// 
			// StartButton
			// 
			this.StartButton.Location = new System.Drawing.Point(8, 12);
			this.StartButton.Name = "StartButton";
			this.StartButton.Size = new System.Drawing.Size(72, 24);
			this.StartButton.TabIndex = 0;
			this.StartButton.Text = "Start";
			this.StartButton.Click += new System.EventHandler(this.StartButton_Click);
			// 
			// StopButton
			// 
			this.StopButton.Location = new System.Drawing.Point(88, 12);
			this.StopButton.Name = "StopButton";
			this.StopButton.Size = new System.Drawing.Size(72, 24);
			this.StopButton.TabIndex = 1;
			this.StopButton.Text = "Stop";
			this.StopButton.Click += new System.EventHandler(this.StopButton_Click);
			// 
			// OpenDlg
			// 
			this.OpenDlg.DefaultExt = "wav";
			this.OpenDlg.Filter = "WAV files|*.wav";
			// 
			// MainForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(250, 47);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.StopButton,
																		  this.StartButton});
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
			this.MaximizeBox = false;
			this.MinimizeBox = false;
			this.Name = "MainForm";
			this.Text = "Full-duplex audio sample";
			this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() {
			Application.Run(new MainForm());
		}

		private WaveOutPlayer m_Player;
		//private WaveLib.WaveInRecorder m_Recorder;
		private FifoStream m_Fifo = new FifoStream();
		private XTCast.Mp3.Decode.DecodeFilter decode;

		private byte[] m_PlayBuffer;
		private byte[] m_RecBuffer;

		private void Filler(IntPtr data, int size) {
			if (m_PlayBuffer == null || m_PlayBuffer.Length < size)
				m_PlayBuffer = new byte[size];
			if (m_Fifo.Length >= size)
				m_Fifo.Read(m_PlayBuffer, 0, size);
			else
				for (int i = 0; i < m_PlayBuffer.Length; i++)
					m_PlayBuffer[i] = 0;
			System.Runtime.InteropServices.Marshal.Copy(m_PlayBuffer, 0, data, size);
		}

		private void DataArrived(IntPtr data, int size) {
			if (m_RecBuffer == null || m_RecBuffer.Length < size)
				m_RecBuffer = new byte[size];
			System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size);
			m_Fifo.Write(m_RecBuffer, 0, m_RecBuffer.Length);
		}

		private void Stop() {
			if (m_Player != null)
				try {
					m_Player.Dispose();
				}
				finally {
					m_Player = null;
				}
			if (thd != null)
				try {
					thd.Abort();
				}
				finally {
					thd = null;
				}

/*			if (m_Recorder != null)
				try {
					m_Recorder.Dispose();
				}
				finally {
					m_Recorder = null;
				}*/
			m_Fifo.Flush(); // clear all pending data
		}

		private void Run() {
			while(true) {
				try {
					//FileStream fs = new FileStream(@"M:\2 Unlimited\Get Ready\01 - Get Ready For This (Orchestral Mix).mp3",FileMode.Open,FileAccess.Read);

					WebRequest wr = WebRequest.Create("http://localhost:80/XTCast/listen.ashx");
					WebResponse resp = wr.GetResponse();
					try {
						MP3FrameReader mp3 = new MP3FrameReader(resp.GetResponseStream());
						FrameReadInfo i = new FrameReadInfo(32768,2000);
						decode = new XTCast.Mp3.Decode.DecodeFilter(m_Fifo);
						while(true) {
							decode.Write(mp3.ReadFrames(i),0,i.ActualLength);
							while (m_Fifo.Length>304 * 1024)
								Thread.Sleep(TimeSpan.FromSeconds((m_Fifo.Length-(89 * 512))/fmt.nAvgBytesPerSec));
						}
					}
					finally {
						resp.Close();
					}
				} catch ( ThreadAbortException) {
					m_Fifo.Flush();
				} catch ( Exception ex ) {
					Console.WriteLine(ex.ToString());
				}
			}
		}

		Thread thd;
		WaveFormat fmt = new WaveFormat(44100,16,2);
		private void Start() {
			Stop();
			try {
				m_Player = new WaveOutPlayer(-1, fmt, 16384, 5, new BufferFillEventHandler(Filler));
				thd = new Thread(new ThreadStart(Run));
				thd.IsBackground=true;
				thd.Start();
			}
			catch {
				Stop();
				throw;
			}
		}

		private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
			Stop();
		}

		private void StartButton_Click(object sender, System.EventArgs e) {
			Start();
		}

		private void StopButton_Click(object sender, System.EventArgs e) {
			Stop();
		}
	}
}
